<script>
import classNames from 'classnames'

import { toObject } from '@/utils/util'
import Bar from './Scrollbar'
import {
  addResizeListener,
  removeResizeListener,
  getScrollbarWidth
} from '@/utils/dom'
import { ConfigConsumerProps } from '../config-provider'

export default {
  name: 'ScrollView',
  components: { Bar },
  inject: {
    configProvider: { default: () => ConfigConsumerProps }
  },
  props: {
    trigger: String,
    native: Boolean,
    wrapStyle: {},
    wrapClass: {},
    contentClass: {},
    contentStyle: {},
    noresize: Boolean,
    // 对树不需要hover交互
    simple: Boolean,
    tag: {
      type: String,
      default: 'div'
    }
  },

  data () {
    return {
      sizeWidth: '0',
      sizeHeight: '0',
      moveX: 0,
      moveY: 0
    }
  },

  computed: {
    wrap () {
      return this.$refs.wrap
    }
  },

  render (h) {
    let gutter = getScrollbarWidth()
    let style = this.wrapStyle

    const getPrefixCls = this.configProvider.getPrefixCls
    const prefixCls = getPrefixCls('scroll-view')

    const viewClass = classNames(`${prefixCls}`)
    const contentClass = classNames([
      `${prefixCls}__content`,
      this.contentClass
    ])
    const wrapClass = classNames([`${prefixCls}__wrap`, this.wrapClass], {
      [`${prefixCls}__wrap`]: !gutter
    })

    if (gutter) {
      const gutterWith = `-${gutter}px`
      // const gutterStyle = `margin-bottom: ${gutterWith}; margin-right: ${gutterWith};`
      const gutterStyle = `margin-right: ${gutterWith};`

      if (Array.isArray(this.wrapStyle)) {
        style = toObject(this.wrapStyle)
        style.marginRight = style.marginBottom = gutterWith
      } else if (typeof this.wrapStyle === 'string') {
        style += gutterStyle
      } else {
        style = gutterStyle
      }
    }
    const view = h(
      this.tag,
      {
        class: contentClass,
        style: this.contentStyle,
        ref: 'resize'
      },
      this.$slots.default
    )
    const wrap = (
      <div
        ref="wrap"
        style={style}
        onScroll={this.handleScroll}
        class={wrapClass}
      >
        {[view]}
      </div>
    )
    let nodes

    if (!this.native) {
      nodes = [
        wrap,
        <Bar
          ref="verticalBar"
          vertical
          move={this.moveY}
          size={this.sizeHeight}
          class={{ 'is-simple': this.simple }}
        />
      ]
    } else {
      nodes = [
        <div ref="wrap" class={wrapClass} style={style}>
          {[view]}
        </div>
      ]
    }
    return h('div', { class: viewClass }, nodes)
  },

  methods: {
    handleScroll () {
      const wrap = this.wrap

      this.moveY = (wrap.scrollTop * 100) / wrap.clientHeight
      this.moveX = (wrap.scrollLeft * 100) / wrap.clientWidth
    },

    update () {
      let heightPercentage, widthPercentage
      const wrap = this.wrap
      if (!wrap) return

      heightPercentage = (wrap.clientHeight * 100) / wrap.scrollHeight
      widthPercentage = (wrap.clientWidth * 100) / wrap.scrollWidth

      this.sizeHeight = heightPercentage < 100 ? heightPercentage + '%' : ''
      this.sizeWidth = widthPercentage < 100 ? widthPercentage + '%' : ''
    },

    scrollToBottom () {
      this.$refs.wrap.scrollTo(0, this.$refs.resize.clientHeight)
    }
  },

  mounted () {
    if (this.native) return
    this.$nextTick(this.update)
    !this.noresize && addResizeListener(this.$refs.resize, this.update)
  },

  beforeDestroy () {
    if (this.native) return
    !this.noresize && removeResizeListener(this.$refs.resize, this.update)
  }
}
</script>
